package com.douqu.game.plantwar.core.utils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.*;

public class BeanMapConvertUtils {
    public static List<String> baseDataType = new ArrayList<>();
    static {
        baseDataType.add("byte");
        baseDataType.add("short");
        baseDataType.add("int");
        baseDataType.add("long");
        baseDataType.add("double");
        baseDataType.add("float");
        baseDataType.add("boolean");
    }

    /**
     * Converts a map to a JavaBean.
     *
     * @param type type to convert
     * @param map map to convert
     * @return JavaBean converted
     * @throws java.beans.IntrospectionException failed to get class fields
     * @throws IllegalAccessException failed to instant JavaBean
     * @throws InstantiationException failed to instant JavaBean
     * @throws java.lang.reflect.InvocationTargetException failed to call setters
     */
    public static final <T> T toBean(Class<T> type, Map<String, ? extends Object> map) {
        if (map == null)
            return null;
        T obj = null;
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(type);
            obj = type.newInstance();
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (int i = 0; i < propertyDescriptors.length; i++) {
                PropertyDescriptor descriptor = propertyDescriptors[i];
                String propertyName = descriptor.getName();
                if (map.containsKey(propertyName)) {
                    Object value = map.get(propertyName);
                    if (value == null) {
                        continue;
                    }
                    Method method = descriptor.getWriteMethod();
                    Class<?>[] clazzArr = method.getParameterTypes();
                    String claName = clazzArr[0].getName();
                    if ("java.lang.String".equals(claName)) {
                        value = value.toString();
                    } else if ("java.lang.Short".equals(claName)) {
                        value = Short.parseShort(value.toString());
                    } else if ("java.lang.Integer".equals(claName)) {
                        value = Integer.parseInt(value.toString());
                    } else if ("java.lang.Long".equals(claName)) {
                        value = Long.parseLong(value.toString());
                    } else if ("java.lang.Double".equals(claName)) {
                        value = Double.parseDouble(value.toString());
                    } else if ("java.lang.Float".equals(claName)) {
                        value = Float.parseFloat(value.toString());
                    } else if ("java.math.BigDecimal".equals(claName)) {
                        value = new BigDecimal(value.toString());
                    } else if ("java.util.Set".equals(claName)){
                        ArrayList list = (ArrayList)value;
                        Set set = new HashSet(list);
                        value = set;
                    } else if (baseDataType.contains(claName)){

                    }
                    Object[] args = new Object[1];
                    args[0] = value;
                    method.invoke(obj, args);
                }
            }

        }catch (Exception e){
            e.printStackTrace();
            LogUtils.error("map to bean error");
        }
        return obj;
    }

    /**
     * Converts a JavaBean to a SortedMap
     * @param bean
     * @return
     * @throws java.beans.IntrospectionException
     * @throws IllegalAccessException
     * @throws java.lang.reflect.InvocationTargetException
     */
    public static final SortedMap toSortedMap(Object bean) throws IntrospectionException, IllegalAccessException, InvocationTargetException {
        SortedMap params = new TreeMap();
        BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (int i = 0; i< propertyDescriptors.length; i++) {
            PropertyDescriptor descriptor = propertyDescriptors[i];
            String propertyName = descriptor.getName();
            if (!propertyName.equals("class") && !propertyName.equals("parameters")) {
                Method readMethod = descriptor.getReadMethod();
                Object result = readMethod.invoke(bean, new Object[0]);
                if (result != null && !"".equals(result)) {
                    params.put(propertyName, result);
                }
            }
        }
        return params;
    }
}
